﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

namespace AutoCadConvert
{
    public class Block:BspObject
    {
        //private static bool s_Fail = false;
        public BlockReference m_Block=null;
        public Block(Autodesk.AutoCAD.DatabaseServices.BlockReference entity)
        {
            m_Block = entity;
        }
        public static void RecurBlockReference(BlockReference blkRef, Autodesk.AutoCAD.Geometry.Scale3d scale, Point basePt,Point offset, ref List<Point> ptLst)
        {//取所有点数据
            //if (blkRef.IsDynamicBlock)
            //{
            //    string error = "\n不支持动态块";
            //    DwgConvert.PutMessage(error);
            //}
            //else
            //{
            using (Transaction ts = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
            {
                BlockTableRecord btRec = ts.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
                foreach (ObjectId objid in btRec)
                {
                    DBObject dbobj = ts.GetObject(objid, OpenMode.ForRead);
                    if (dbobj is BlockReference)
                    {
                        RecurBlockReference(dbobj as BlockReference, (dbobj as BlockReference).ScaleFactors, basePt,offset, ref ptLst);
                    }
                    else if (dbobj is Autodesk.AutoCAD.DatabaseServices.Line)
                    {
                        Autodesk.AutoCAD.DatabaseServices.Line entity = dbobj as Autodesk.AutoCAD.DatabaseServices.Line;
                        Point ptS = new Point()
                        {
                            X = (entity.StartPoint.X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                            Y = (entity.StartPoint.Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                            Z = (entity.StartPoint.Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                        };
                        Point ptE = new Point()
                        {
                            X = (entity.EndPoint.X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                            Y = (entity.EndPoint.Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                            Z = (entity.EndPoint.Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                        };
                        if (!ptLst.Contains(ptS)) ptLst.Add(ptS);
                        if (!ptLst.Contains(ptE)) ptLst.Add(ptE);
                    }
                    else if (dbobj is Autodesk.AutoCAD.DatabaseServices.Polyline)
                    {
                        Autodesk.AutoCAD.DatabaseServices.Polyline entity = dbobj as Autodesk.AutoCAD.DatabaseServices.Polyline;
                        for (int i = 0; i < entity.NumberOfVertices; i++)
                        {
                            if (SegmentType.Line == entity.GetSegmentType(i))
                            {
                                Autodesk.AutoCAD.Geometry.Point3d pttt1 = entity.GetLineSegmentAt(i).StartPoint;
                                Autodesk.AutoCAD.Geometry.Point3d pttt2 = entity.GetLineSegmentAt(i).EndPoint;
                                Point ptS = new Point()
                                {
                                    X = (entity.GetLineSegmentAt(i).StartPoint.X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    Y = (entity.GetLineSegmentAt(i).StartPoint.Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    Z = (entity.GetLineSegmentAt(i).StartPoint.Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                };
                                Point ptE = new Point()
                                {
                                    X = (entity.GetLineSegmentAt(i).EndPoint.X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    Y = (entity.GetLineSegmentAt(i).EndPoint.Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    Z = (entity.GetLineSegmentAt(i).EndPoint.Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                };
                                if (!ptLst.Contains(ptS)) ptLst.Add(ptS);
                                if (!ptLst.Contains(ptE)) ptLst.Add(ptE);
                            }
                        }
                    }
                    else if (dbobj is Autodesk.AutoCAD.DatabaseServices.Arc)
                    {
                        Autodesk.AutoCAD.DatabaseServices.Arc entity = dbobj as Autodesk.AutoCAD.DatabaseServices.Arc;
                        ptLst.Add(new Point() {
                            X = (entity.GetPointAtDist(entity.Length / 4).X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                            Y = (entity.GetPointAtDist(entity.Length / 4).Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                            Z = (entity.GetPointAtDist(entity.Length / 4).Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                        });
                        ptLst.Add(new Point() {
                            X = (entity.GetPointAtDist(entity.Length / 4 * 2).X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                            Y = (entity.GetPointAtDist(entity.Length / 4 * 2).Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                            Z = (entity.GetPointAtDist(entity.Length / 4 * 2).Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                        });
                        ptLst.Add(new Point() {
                            X = (entity.GetPointAtDist(entity.Length / 4 * 3).X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                            Y = (entity.GetPointAtDist(entity.Length / 4 * 3).Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                            Z = (entity.GetPointAtDist(entity.Length / 4 * 3).Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                        });
                    }
                    else if (dbobj is Autodesk.AutoCAD.DatabaseServices.Hatch)
                    { }
                    else
                    {
                        System.Diagnostics.Trace.WriteLine("Block Data______________" + dbobj.GetType().FullName);
                    }
                }
            }
            //}
        }
        public static void RecurBlockReference(BlockReference blkRef, Autodesk.AutoCAD.Geometry.Scale3d scale, Point3d basePt, Point offset,double angle, ref List<List<Point>> ptLst)
        {//取闭合数据
            //if (blkRef.IsDynamicBlock)
            //{
            //    string error = "\n不支持动态块";
            //    DwgConvert.PutMessage(error);
            //}
            //else
            //{
            using (Transaction ts = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
            {
                BlockTableRecord btRec = ts.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
                foreach (ObjectId objid in btRec)
                {
                    DBObject dbobj = ts.GetObject(objid, OpenMode.ForRead);
                    if (dbobj is BlockReference)
                    {
                        RecurBlockReference(dbobj as BlockReference, (dbobj as BlockReference).ScaleFactors, basePt, offset,angle, ref ptLst);
                    }
                    else if (dbobj is Autodesk.AutoCAD.DatabaseServices.Hatch)
                    { }
                    else if (dbobj is Autodesk.AutoCAD.DatabaseServices.Polyline)
                    {
                        List<Point> lst = new List<Point>();
                        Autodesk.AutoCAD.DatabaseServices.Polyline entity = dbobj as Autodesk.AutoCAD.DatabaseServices.Polyline;
                        if(!entity.Closed)
                        {
                            DwgConvert.PutMessage("图块有多段线未闭合");
                            return;
                        }
                        for (int i = 0; i < entity.NumberOfVertices; i++)
                        {
                            if (SegmentType.Line == entity.GetSegmentType(i))
                            {
                                Autodesk.AutoCAD.Geometry.Point3d pttt1 = entity.GetLineSegmentAt(i).StartPoint;
                                Autodesk.AutoCAD.Geometry.Point3d pttt2 = entity.GetLineSegmentAt(i).EndPoint;
                                Point3d ptS = new Point3d
                                (
                                    (entity.GetLineSegmentAt(i).StartPoint.X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    (entity.GetLineSegmentAt(i).StartPoint.Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    (entity.GetLineSegmentAt(i).StartPoint.Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                ).RotateBy(angle, new Vector3d(0, 0, 1), new Point3d(basePt.X-offset.X,basePt.Y-offset.Y,basePt.Z-offset.Z));
                                Point3d ptE = new Point3d
                                (
                                    (entity.GetLineSegmentAt(i).EndPoint.X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    (entity.GetLineSegmentAt(i).EndPoint.Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    (entity.GetLineSegmentAt(i).EndPoint.Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                ).RotateBy(angle,new Vector3d(0,0,1), new Point3d(basePt.X - offset.X, basePt.Y - offset.Y, basePt.Z - offset.Z));
                                if(!lst.Contains(new Point(ptS))) lst.Add(new Point(ptS));
                                if (!lst.Contains(new Point(ptE))) lst.Add(new Point(ptE));
                            }
                            else if(SegmentType.Arc == entity.GetSegmentType(i))
                            {
                                lst.Add(new Point(new Point3d
                                (
                                    (entity.GetPointAtDist(entity.Length / 4).X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    (entity.GetPointAtDist(entity.Length / 4).Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    (entity.GetPointAtDist(entity.Length / 4).Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                ).RotateBy(angle, new Vector3d(0, 0, 1), new Point3d(basePt.X - offset.X, basePt.Y - offset.Y, basePt.Z - offset.Z))));
                                lst.Add(new Point(new Point3d
                                (
                                    (entity.GetPointAtDist(entity.Length / 4 * 2).X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    (entity.GetPointAtDist(entity.Length / 4 * 2).Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    (entity.GetPointAtDist(entity.Length / 4 * 2).Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                ).RotateBy(angle, new Vector3d(0, 0, 1), new Point3d(basePt.X - offset.X, basePt.Y - offset.Y, basePt.Z - offset.Z))));
                                lst.Add(new Point(new Point3d
                                (
                                    (entity.GetPointAtDist(entity.Length / 4 * 3).X - btRec.Origin.X) * Math.Abs(scale.X) + basePt.X - offset.X,
                                    (entity.GetPointAtDist(entity.Length / 4 * 3).Y - btRec.Origin.Y) * Math.Abs(scale.Y) + basePt.Y - offset.Y,
                                    (entity.GetPointAtDist(entity.Length / 4 * 3).Z - btRec.Origin.Z) * Math.Abs(scale.Z) + basePt.Z - offset.Z
                                ).RotateBy(angle, new Vector3d(0, 0, 1), new Point3d(basePt.X - offset.X, basePt.Y - offset.Y, basePt.Z - offset.Z))));
                            }
                        }
                        ptLst.Add(lst);
                    }
                    else
                    {
                        DwgConvert.PutMessage("请使用闭合多段线描述该类型图块");
                    }
                }
            }
            //}
        }
    }
}
